package br.com.raulfortes.guardasenha.dao;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.crypto.Cipher;
import javax.crypto.SealedObject;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import br.com.raulfortes.guardasenha.beans.Arquivo;


public class ArquivoDAO {

	 // 8-byte Salt
    private byte[] salt = {
        (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
        (byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
    };

    // Iteration count
    private int iterationCount = 19;

	public void save(File file, Arquivo arquivo, String senha) throws Exception {
		try {
			KeySpec keySpec = new PBEKeySpec(senha.toCharArray(), salt, iterationCount);
            SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);			
            
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
            
			Cipher ecipher = Cipher.getInstance(key.getAlgorithm());
			ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
			
	        SealedObject so = new SealedObject(arquivo, ecipher);
	        
			FileOutputStream fos = new FileOutputStream(file);
			GZIPOutputStream gzos = new GZIPOutputStream(fos);
			ObjectOutputStream out = new ObjectOutputStream(gzos);
			out.writeObject(so);
			out.flush();
			out.close();
		} catch (Exception e) {
			System.out.println(e);
			e.printStackTrace();
			throw new Exception("Erro ao salvar arquivo: " + file.getName());
		}
	}

	public Arquivo load(File file, String senha) throws Exception {
		try {
			FileInputStream fis = new FileInputStream(file);
			GZIPInputStream gzis = new GZIPInputStream(fis);
			ObjectInputStream in = new ObjectInputStream(gzis);
			SealedObject so = (SealedObject) in.readObject();
			in.close();
			
			KeySpec keySpec = new PBEKeySpec(senha.toCharArray(), salt, iterationCount);
            SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);			
            
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
			
			Cipher dcipher = Cipher.getInstance(key.getAlgorithm());
	        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
	    
	        Arquivo arquivo = (Arquivo)so.getObject(dcipher);
	        
			return arquivo;
		} catch (Exception e) {
			System.out.println(e);
			e.printStackTrace();
			throw new Exception("Erro ao carregar arquivo: " + file.getName());
		}
		
	}
    
}
